package com.main.tcp;

import com.ModbusClientFactory;
import com.ModbusFunctionInterface;
import com.constant.FuncitonCodeEnum;
import com.exception.ModbusException;
import com.function.FunctionFactory;
import com.function.base.BaseFunctionAction;
import com.response.JsonResult;

import java.io.IOException;


//@Slf4j
public class ModbusTcpHelper implements ModbusFunctionInterface {

    private ModbusTcpClient client;

    private ModbusTcpHelper(){
        init();
    }

    private void init() {
        try {
            client = ModbusClientFactory.createModbusMasterTCP("127.0.0.1", 502);
            client.connect();
        } catch (IOException e) {
            //TODO //记录日志
            e.printStackTrace();
        }
    }


    static private class SingletonHolder {
        final static private ModbusTcpHelper instance = new ModbusTcpHelper();
    }

    static public ModbusTcpHelper getInstance() {
        return SingletonHolder.instance;
    }


    /**
     * 读线圈
     * @param startAddress 开始地址
     * @param quantity 读取的地址数
     * @return
     * @throws ModbusException
     * @throws IOException
     */
    @Override
    public JsonResult readCoils(int startAddress, int quantity) throws ModbusException, IOException {
        BaseFunctionAction functionAction = FunctionFactory.getInstance().createMessage(
                FuncitonCodeEnum.READ_COILS.toInt(),
                startAddress,
                quantity);
        return client.process(functionAction);
    }

    /**
     * 读离散输入
     * @param startAddress 开始地址
     * @param quantity 读取的地址数
     * @return
     * @throws ModbusException
     * @throws IOException
     */
    @Override
    public JsonResult readDiscreteInputs(int startAddress, int quantity) throws ModbusException, IOException {
        BaseFunctionAction functionAction = FunctionFactory.getInstance().createMessage(
                FuncitonCodeEnum.READ_DISCRETE_INPUTS.toInt(),
                startAddress,
                quantity);
        return client.process(functionAction);
    }

    /**
     * 读保持寄存器
     * @param startAddress 开始地址
     * @param quantity 读取的地址数
     * @return
     * @throws IOException
     * @throws ModbusException
     */
    @Override
    public JsonResult readHoldingRegisters(int startAddress, int quantity) throws IOException, ModbusException {
        BaseFunctionAction functionAction = FunctionFactory.getInstance().createMessage(
                FuncitonCodeEnum.READ_HOLDING_REGISTERS.toInt(),
                startAddress,
                quantity);
        return client.process(functionAction);
    }

    /**
     * 读输入寄存器
     * @param startAddress 开始地址
     * @param quantity 读取的地址数
     * @return
     * @throws IOException
     * @throws ModbusException
     */
    @Override
    public JsonResult readInputRegisters(int startAddress, int quantity) throws IOException, ModbusException {
        BaseFunctionAction functionAction = FunctionFactory.getInstance().createMessage(
                FuncitonCodeEnum.READ_INPUT_REGISTERS.toInt(),
                startAddress,
                quantity);
        return client.process(functionAction);
    }

    /**
     * 写单个线圈
     * @param  writingAddress 需要写的地址
     * @param value 值
     * @return
     * @throws IOException
     * @throws ModbusException
     */
    @Override
    public JsonResult writeCoil(int writingAddress, int value) throws IOException, ModbusException {
        BaseFunctionAction functionAction = FunctionFactory.getInstance().createMessage(
                FuncitonCodeEnum.WRITE_SINGLE_COIL.toInt(),
                writingAddress,
                value);
        return client.process(functionAction);
    }

    /**
     * 写单个保持寄存器
     * @param writingAddress 需要写的地址
     * @param value 值
     * @return
     * @throws IOException
     * @throws ModbusException
     */
    @Override
    public JsonResult writeHoldingRegister(int writingAddress, int value) throws IOException, ModbusException {
        BaseFunctionAction functionAction = FunctionFactory.getInstance().createMessage(
                FuncitonCodeEnum.WRITE_SINGLE_REGISTER.toInt(),
                writingAddress,
                value);
        return client.process(functionAction);
    }

    /**
     * 批量写线圈
     * @param writingAddress 需要写的地址
     * @param values 值
     * @return
     * @throws IOException
     * @throws ModbusException
     */
    @Override
    public JsonResult multipleWriteCoils(int writingAddress, int[] values) throws IOException, ModbusException {
        BaseFunctionAction functionAction = FunctionFactory.getInstance().createMessage(
                FuncitonCodeEnum.WRITE_MULTIPLE_COILS.toInt(),
                writingAddress,
                values);
        return client.process(functionAction);
    }

    /**
     * 批量写寄存器
     * @param writingAddress 需要写的地址
     * @param values 值
     * @return
     * @throws IOException
     * @throws ModbusException
     */
    @Override
    public JsonResult multipleWriteHoldingRegisters(int writingAddress, int[] values) throws IOException, ModbusException {
        BaseFunctionAction functionAction = FunctionFactory.getInstance().createMessage(
                FuncitonCodeEnum.WRITE_MULTIPLE_REGISTERS.toInt(),
                writingAddress,
                values);
        return client.process(functionAction);
    }

    public static void main(String[] args) throws IOException, ModbusException {
        ModbusTcpHelper helper = new ModbusTcpHelper();
//        JsonResult js = helper.readCoils(1, 12); // 读线圈
//        JsonResult js = helper.readDiscreteInputs(1, 12);// 读离散输入
        JsonResult js = helper.readHoldingRegisters(1, 12);// 读保持寄存器值
//        JsonResult js = helper.readInputRegisters(1, 12);// 读输入寄存器值

        // 输出值
        js.getData().forEach(rs -> System.out.println(rs.getAddress() + " : " + rs.getValue()));

//        JsonResult js = helper.writeCoil(6, 1);// 写单个线圈
//        JsonResult js = helper.writeHoldingRegister(8, 1111);// 写单个寄存器
//        JsonResult js = helper.multipleWriteCoils(2, new int[]{1,0,1,0,1});// 批量写线圈
//        JsonResult js = helper.multipleWriteHoldingRegisters(2, new int[]{111,22,33,7,45}); // 批量写寄存器
    }

}
